package com.bestvike.stone.core.lang;

import com.alibaba.fastjson.TypeReference;
import com.bestvike.stone.core.reflect.TypeUtils;
import com.bestvike.stone.core.serialization.JsonSerializer;

import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

/**
 * Bean 工具类, 依赖 fastjson
 * Created by 许崇雷 on 2017/7/13.
 */
public final class BeanUtils {
    /**
     * 转换为 Map
     *
     * @param obj   对象
     * @param <TIn> 入参类型
     * @return 字典
     */
    @SuppressWarnings("unchecked")
    public static <TIn> Map<String, Object> toMap(TIn obj) {
        if (obj == null)
            return null;
        if (obj instanceof Map)
            return (Map<String, Object>) obj;
        return JsonSerializer.deserializeMap(JsonSerializer.serialize(obj));
    }

    /**
     * 转换为 Bean
     *
     * @param obj    对象
     * @param clazz  返回类型
     * @param <TIn>  入参类型
     * @param <TOut> 返回类型
     * @return 对象
     */
    public static <TIn, TOut> TOut toBean(TIn obj, Class<TOut> clazz) {
        return toBean(obj, (Type) clazz);
    }

    /**
     * 转换为 Bean
     *
     * @param obj    对象
     * @param type   返回类型
     * @param <TIn>  入参类型
     * @param <TOut> 返回类型
     * @return 对象
     */
    public static <TIn, TOut> TOut toBean(TIn obj, TypeReference<TOut> type) {
        return toBean(obj, type.getType());
    }

    /**
     * 转换为 Bean
     *
     * @param obj    对象
     * @param type   返回类型
     * @param <TIn>  入参类型
     * @param <TOut> 返回类型
     * @return 对象
     */
    @SuppressWarnings("unchecked")
    public static <TIn, TOut> TOut toBean(TIn obj, Type type) {
        if (obj == null)
            return null;
        Class<?> clazz = TypeUtils.getRawClass(type);
        if (clazz.isInstance(obj))
            return (TOut) obj;
        return JsonSerializer.deserialize(JsonSerializer.serialize(obj), type);
    }

    /**
     * 转换为 List
     *
     * @param obj           集合
     * @param clazz         返回元素类型
     * @param <TCollection> 集合类型
     * @param <TOut>        返回元素类型
     * @return 对象集合
     */
    public static <TCollection, TOut> List<TOut> toList(TCollection obj, Class<TOut> clazz) {
        if (obj == null)
            return null;
        return JsonSerializer.deserializeArray(JsonSerializer.serialize(obj), clazz);
    }
}
